//=============================================================================
// XBus 
//-----------------------------------------------------------------------------
// File        : xbus_cell.c
// Description : 
// Author      : Ismail Sabry
// Date        : 1/30/2009
//=============================================================================
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <xbus.h>

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int XBUS_init_cell(t_XBUS_cell *cell)
{
  cell->head.magictag = XBUS_MAGICTAG_CELL;
  cell->head.next     = 0;
  cell->head.len      = 0;

  return 0;
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
t_XBUS_cell *XBUS_get_cell_by_index(t_XBUS *xbus, 
				    t_XBUS_module  *module, 
				    unsigned int icell)
{
  unsigned int   offset, sz_cell;
  t_XBUS_cell    *cell;

  if(icell >= xbus->head.nb_cell) {
    printf("XBus bad cell index (%u, max %d)\n", icell, xbus->head.nb_cell);
    return((t_XBUS_cell *)-1);
  } 

  sz_cell = sizeof(t_XBUS_cell_header)   + (xbus->head.size_cell);
  offset  = sizeof(t_XBUS_module_header) + (icell * sz_cell);

  cell = (t_XBUS_cell *)((unsigned char *)module + offset);

  //printf("cell(%u) %p - xbus %p / module %p / offset %u \n", icell, cell, xbus, module, offset);

  return(cell);
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int XBUS_chain_cell(t_XBUS_cell *cell, t_XBUS_cell *next)
{
  cell->head.next = (int)next - (int)cell;
  return 0;
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
t_XBUS_cell *XBUS_get_next_cell(t_XBUS_cell *cell)
{
  t_XBUS_cell    *next;

  next = (t_XBUS_cell *)((unsigned char *)cell + cell->head.next);

  return(next);
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int XBUS_write_cell(t_XBUS *xbus, t_XBUS_cell *cell, unsigned char *buf, unsigned int len)
{
  if(len > xbus->head.size_cell) {
    printf("XBus invalid data size %d (max %d)\n", len, xbus->head.size_cell);
    return -1;
  }
  
  // copt buf -> cell->body
  memcpy (&cell->body, buf, len);
  cell->head.len = len;

  return len;
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int XBUS_read_cell(t_XBUS *xbus, t_XBUS_cell *cell, unsigned char *buf, unsigned int len)
{
  int      rlen;

  if(len > xbus->head.size_cell) {
    printf("XBus invalid data size %d (max %d)\n", len, xbus->head.size_cell);
    return -1;
  }

  rlen = (cell->head.len < len)?cell->head.len:len;

  // copy cell->body -> buf
  memcpy (buf, &cell->body, rlen);

  return rlen;
}
